package com.thitech.sif.utils;

import java.lang.reflect.Method;

/**
 * 反射工具类
 * @author shisheng.lian
 * @date 2014-08-10
 *
 */
public class ReflectRunner {
	private static ReflectRunner instance = new ReflectRunner();

	private ReflectRunner() {
	}

	public static ReflectRunner getInstance() {
		return instance;
	}

	public Object invokeMethod(Object _owner, String _methodName, Object[] _args)
			throws Exception {
		return invokeMethod(_owner, _methodName, _args, null, false);
	}

	public Object invokeMethod(Object _owner, String _methodName,
			Object[] _args, Class<?>[] _argsClass) throws Exception {
		return invokeMethod(_owner, _methodName, _args, _argsClass, false);
	}

	public Object invokeMethod(Object _owner, String _methodName,
			Object[] _args, boolean _sync) throws Exception {
		return invokeMethod(_owner, _methodName, _args, null, _sync);
	}

	public Object invokeMethod(Object _owner, String _methodName,
			Object[] _args, Class<?>[] _argsClass, boolean _sync)
			throws Exception {
		Object v = null;

		Class<?> ownerClass = _owner.getClass();
		Class<?>[] argsClass = getClassArrayByArgs(_args, _argsClass);
		Method method = ownerClass.getMethod(_methodName, argsClass);
		if (_sync == true) {
			synchronized (_owner) {
				v = method.invoke(_owner, _args);
			}
		} else {
			v = method.invoke(_owner, _args);
		}
		return v;
	}

	private Class<?>[] getClassArrayByArgs(Object[] _args, Class<?>[] _argsClass) {
		Class<?>[] argsClass = new Class[_args.length];
		if (_argsClass == null) {
			for (int i = 0, j = _args.length; i < j; i++) {
				argsClass[i] = _args[i].getClass();
			}
		} else {
			for (int i = 0, j = _args.length; i < j; i++) {
				if (_argsClass[i] != null) {
					argsClass[i] = _argsClass[i];
				} else {
					argsClass[i] = _args[i].getClass();
				}
			}
		}
		return argsClass;
	}

	public Object invokeStaticMethod(Class<?> _ownerClass, String _methodName,
			Object[] _args) throws Exception {
		Class<?>[] argsClass = new Class[_args.length];
		for (int i = 0, j = _args.length; i < j; i++) {
			argsClass[i] = _args[i].getClass();
		}
		Method method = _ownerClass.getMethod(_methodName, argsClass);
		return method.invoke(null, _args);
	}
}
